package com.yu.util;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.ConnectException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import net.sf.json.JSONArray;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;


public class CommonUtil {
	// 订单号开头字母
	public final static String ORDER_HEAD = "E";

	/**
	 * 生成不重复的订单号
	 * 
	 * @return
	 */
	public static String createOrderSn() {
		String orderSn = null;

		while (true) {
			orderSn = GeneratorNumber.get12Id();
			if (!StringUtil.isEmpty(orderSn)) {
				break;
			}
		}

		return "R" + orderSn;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static List parsePHPString(String str) {
		/* 定义字符串解析的正则表达式，意在取出字符串中双引号的内容，取出的数据包括双引号 */
		Pattern p = Pattern.compile("\"(.*?)\"");
		// 存放分割的字符串，包含子列表，每个子列表存放一系列有个规律的某对象的属性和值
		List result = new ArrayList();

		/* 根据“{}”分割字符串内容，将字符串中{}中的内容分割成数据 */
		String[] sts = str.split("[{}]{1,2}");

		for (int i = 1; i < sts.length; i++) {
			/* 分类处理，取出包括双引号的子字符串 */
			if (sts[i].indexOf("\"") != -1) {
				// 存放子字符串，内容为某对象有规律的属性和值
				List SubList = new ArrayList();
				/* 匹配对应的字符串截取规则 */
				Matcher m = p.matcher(sts[i]);

				/* 循环取出匹配的值 */
				while (m.find()) {
					String element = m.group();
					/* 去掉每个元素的双引号 */
					element = element.replaceAll("\"", "");

					SubList.add(element);
				}

				result.add(SubList);
			}

		}

		return result;
	}

	// /**
	// * 解析php字符格式的商品信息
	// *
	// * @param strs 格式为：
	// *
	// "a:2:{i:0;a:3:{s:2:\"id\";s:2:\"33\";s:4:\"name\";s:12:\"山西汾酒\";s:5:\"price\";s:3:\"100\";}i:1;a:3:{s:2:\"id\";s:2:\"30\";s:4:\"name\";s:20:\"移动20元充值卡\";s:5:\"price\";s:1:\"0\";}}"
	// * @return
	// * @see [类、类#方法、类#成员]
	// */
	// @SuppressWarnings("rawtypes")
	// public static List<GoodsModel> parsePHPToGoodsModel(String strs)
	// {
	// List<GoodsModel> goodsList = new ArrayList<GoodsModel>();
	//
	// List goodsInfo = parsePHPString(strs);
	//
	// for (int j = 0; j < goodsInfo.size(); j++)
	// {
	// GoodsModel goods = new GoodsModel();
	//
	// List subList = (List)goodsInfo.get(j);
	// for (int z = 0; z < subList.size(); z++)
	// {
	//
	// if (subList.get(z).equals("id"))
	// {
	// String id = (String)subList.get(z + 1);
	// goods.setGoodsId(Integer.parseInt(id));
	// }
	//
	// if (subList.get(z).equals("name"))
	// {
	// String name = (String)subList.get(z + 1);
	// goods.setGoodsName(name);
	// }
	//
	// if (subList.get(z).equals("price"))
	// {
	// String price = (String)subList.get(z + 1);
	// goods.setShopPrice(new BigDecimal(price));
	// }
	// }
	// goodsList.add(goods);
	//
	// }
	//
	// return goodsList;
	// }
	//
	/**
	 * 提供精确的小数位四舍五入处理
	 * 
	 * @param b
	 *            操作数
	 * @param scale
	 *            小数点后保留几位
	 * @return
	 */
	public static BigDecimal round(BigDecimal b, int scale) {
		/* 若没有提供保留的小数位，默认保留2位小数 */
		if (scale < 0) {
			scale = 2;
		}

		BigDecimal one = new BigDecimal("1");

		return b.divide(one, scale, BigDecimal.ROUND_HALF_UP);

	}

	/**
	 * 保留2位型小数，以字符串形式返回
	 * 
	 * @param d
	 *            操作数
	 * @return
	 */
	public static String roundDouble(double d) {
		/* 若没有提供保留的小数位，默认保留2位小数 */
		BigDecimal b = new BigDecimal(String.valueOf(d));

		BigDecimal newB = round(b, 2);

		String st = newB.toString();

		double dd = Double.parseDouble(st);

		st = String.valueOf(dd);

		int startIndex = st.indexOf(".");

		String subStr = "";

		String result = "";

		String intStr = st.substring(0, startIndex);

		if (startIndex != -1) {
			subStr = st.substring(startIndex + 1, st.length());

			// 小数位数大于2时，取前两位
			if (subStr.length() > 2) {
				subStr = subStr.substring(0, 2);
			} else if (subStr.length() == 1) {
				subStr = subStr + "0";
			}

			result = intStr + "." + subStr;
		} else {
			result = intStr + ".00";
		}

		return result;

	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// System.out.println(round(new BigDecimal("0.045"), 2));
		// System.out.println(new BigDecimal("0.04").toString());
		// List<GoodsModel> goodsList = new ArrayList<GoodsModel>();
		// String as =
		// "a:2:{i:0;a:3:{s:2:\"id\";s:2:\"33\";s:4:\"name\";s:12:\"山西汾酒\";s:5:\"price\";s:3:\"100\";}i:1;a:3:{s:2:\"id\";s:2:\"30\";s:4:\"name\";s:20:\"移动20元充值卡\";s:5:\"price\";s:1:\"0\";}}";
		//
		// goodsList = CommonUtil.parsePHPToGoodsModel(as);
		//
		// for (GoodsModel g : goodsList)
		// {
		// System.out.println("goodsId=" + g.getGoodsId());
		// System.out.println("goodsName=" + g.getGoodsName());
		// System.out.println("goodsPrice=" + g.getShopPrice());
		// }
		// String str =
		// "O:8:\"stdClass\":1:{s:7:\"default\";a:5:{i:0;s:28:\"赖永初酒--五年陈酿|1\";i:1;s:52:\"赖永初酒（酱香型白酒）--二十年陈酿|2\";i:2;s:49:\"赖永初酒（酱香型白酒）--十年陈酿|3\";i:3;s:49:\"赖永初酒（酱香型白酒）--五年陈酿|4\";i:4;s:12:\"Nokia E925|5\";}}";
		//
		// List<GoodsModel> topicGoods = new ArrayList<GoodsModel>();
		// topicGoods = parsePHPTopicGoods(str);
		// System.out.println(topicGoods.size());
		// String str = "a:1:{s:13:\"package_price\";s:3:\"888\";}";
		// String str =
		// "a:4:{s:12:\"price_ladder\";a:2:{i:0;a:2:{s:6:\"amount\";i:10;s:5:\"price\";d:950;}i:1;a:2:{s:6:\"amount\";i:50;s:5:\"price\";d:900;}}s:15:\"restrict_amount\";i:100;s:13:\"gift_integral\";i:100;s:7:\"deposit\";d:1000;}";
		// System.out.println(parsePHPForPackagePrice(str));
		// String s = "g001:1;g002:2;g003:4;";
		// System.out.println(s.substring(0, s.length()-1));
		List list = parsePHPString("a:0:{}");
		for (int i = 0; i < list.size(); i++) {
			System.out.println(list.get(i));
			String[] str = list.get(i).toString().split(",");
			for (int j = 0; j < str.length; j++) {
				System.out.println(str[j]);
			}
		}
		System.out.println(list);
	}

	
	// 凭证获取（GET）
		public final static String token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";

		/**
		 * 发送https请求
		 * 
		 * @param requestUrl 请求地址
		 * @param requestMethod 请求方式（GET、POST）
		 * @param outputStr 提交的数据
		 * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
		 */
		public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
			JSONObject jsonObject = null;
			try {
				// 创建SSLContext对象，并使用我们指定的信任管理器初始化
				TrustManager[] tm = { new MyX509TrustManager() };
				SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
				sslContext.init(null, tm, new java.security.SecureRandom());
				// 从上述SSLContext对象中得到SSLSocketFactory对象
				SSLSocketFactory ssf = sslContext.getSocketFactory();

				URL url = new URL(requestUrl);
				HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
				conn.setSSLSocketFactory(ssf);
				
				conn.setDoOutput(true);
				conn.setDoInput(true);
				conn.setUseCaches(false);
				// 设置请求方式（GET/POST）
				conn.setRequestMethod(requestMethod);

				// 当outputStr不为null时向输出流写数据
				if (null != outputStr) {
					OutputStream outputStream = conn.getOutputStream();
					// 注意编码格式
					outputStream.write(outputStr.getBytes("UTF-8"));
					outputStream.close();
				}

				// 从输入流读取返回内容
				InputStream inputStream = conn.getInputStream();
				InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
				BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
				String str = null;
				StringBuffer buffer = new StringBuffer();
				while ((str = bufferedReader.readLine()) != null) {
					buffer.append(str);
				}

				// 释放资源
				bufferedReader.close();
				inputStreamReader.close();
				inputStream.close();
				inputStream = null;
				conn.disconnect();
				jsonObject = JSONObject.fromObject(buffer.toString());
			} catch (ConnectException ce) {
	            ce.printStackTrace();
	        } catch (Exception e) {
	            e.printStackTrace();
			}
			return jsonObject;
		}

		/**
		 * 获取接口访问凭证
		 * 
		 * @param appid 凭证
		 * @param appsecret 密钥
		 * @return
		 */
		
		
		/**
		 * URL编码（utf-8）
		 * 
		 * @param source
		 * @return
		 */
		public static String urlEncodeUTF8(String source) {
			String result = source;
			try {
				result = java.net.URLEncoder.encode(source, "utf-8");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
			return result;
		}
		
		/**
		 * 根据内容类型判断文件扩展名
		 * 
		 * @param contentType 内容类型
		 * @return
		 */
		public static String getFileExt(String contentType) {
			String fileExt = "";
			if ("image/jpeg".equals(contentType))
				fileExt = ".jpg";
			else if ("audio/mpeg".equals(contentType))
				fileExt = ".mp3";
			else if ("audio/amr".equals(contentType))
				fileExt = ".amr";
			else if ("video/mp4".equals(contentType))
				fileExt = ".mp4";
			else if ("video/mpeg4".equals(contentType))
				fileExt = ".mp4";
			return fileExt;
		}

	    public static String clobToString(com.mysql.jdbc.Blob clob){
	        if(clob == null) {
	            return null;
	        }
	        try {
	            byte[] b = clob.getBytes(1, (int)clob.length());
	            return new String(b,"utf-8");
	        } catch (Exception es) {
	            es.printStackTrace();
	        }
	        return null;
	    }


	    public static Map<String, Object> parseJSON2Map(String jsonStr){
	        Map<String, Object> map = new HashMap<String, Object>();
	        //最外层解析
	        JSONObject json = JSONObject.fromObject(jsonStr);
	        for(Object k : json.keySet()){
	            Object v = json.get(k);
	            //如果内层还是数组的话，继续解析
	            if(v instanceof JSONArray){
	                List<Map<String, Object>> list = new ArrayList<Map<String,Object>>();
	                Iterator<JSONObject> it = ((JSONArray)v).iterator();
	                while(it.hasNext()){
	                    JSONObject json2 = it.next();
	                    list.add(parseJSON2Map(json2.toString()));
	                }
	                map.put(k.toString(), list);
	            } else {
	                map.put(k.toString(), v);
	            }
	        }
	        return map;
	    }

}
